
#ifndef _TTG_EXTRAS_VALUEWRAPPERS_
#define _TTG_EXTRAS_VALUEWRAPPERS_
#include "Common/Definitions.h"

#include "Operations.h"

namespace ttg_internal
{
	//Wraps given variable as operation.
	template<class T>
	class OperationWrapper :public ttg::extras::Operation<T>
	{
		protected:
			const T *source;
		public:
			inline OperationWrapper(const T *source)
					{ this->source = source; }
			virtual T calculate()
					{ return *source; }
			virtual bool isStatic()
					{ return false; }
	};

	//Wraps given value as operation.
	template<class T>
	class OperationValueWrapper :public ttg::extras::Operation<T>
	{
		protected:
			T source;
		public:
			inline OperationValueWrapper(T source)
					{ this->source = source; }
			virtual T calculate()
					{ return source; }
			virtual bool isStatic()
					{ return true; }
	};

	//Builds vector by float components.
	class OperationVector :public ttg::extras::Operation<ttg::math::vec3f>
	{
		protected:
			Operation<float> *s1;
			Operation<float> *s2;
			Operation<float> *s3;
		public:
			//Creates vector by given sources.
			inline OperationVector(Operation<float> *s1,
								   Operation<float> *s2,
								   Operation<float> *s3)
			{
				this->s1 = s1;
				this->s2 = s2;
				this->s3 = s3;
			}
			//Creates vector by given infos.
			//Note: in case of wrong type throws Error.
			inline OperationVector(OperationInfo *s1,
								   OperationInfo *s2,
								   OperationInfo *s3)
			{
				this->s1 = dynamic_cast<Operation<float> *>(s1);
				this->s2 = dynamic_cast<Operation<float> *>(s2);
				this->s3 = dynamic_cast<Operation<float> *>(s3);
				if (s1 == NULL || s2 == NULL || s3 == NULL)
					throw ttg::Error(ttg::Error::FATAL, "OperationVector", "OperationVector",
									 "Cannot cast OperationInfo to Operation<float>");
			}
			virtual ttg::math::vec3f calculate()
			{
				return ttg::math::vec3f(s1->calculate(),
							 s2->calculate(),
							 s3->calculate());
			}
			virtual bool isStatic()
					{ return s1->isStatic() && s2->isStatic() && s3->isStatic(); }
			virtual ~OperationVector()
			{
				if (s2 != s3 && s1 != s3)
				{
					SAFE_DELETE(s3);
				}
				if (s1 != s2)
				{
					SAFE_DELETE(s2);
				}
				SAFE_DELETE(s1);
			}
	};
}

#endif
